// 最终目的  是 对象合并 {created: [a,b]}

export const HOOKS = [
  "beforeCreate",
  "created",
  "beforeMount",
  "mounted",
  "beforeUpdate",
  "updated",
  "beforeDestory",
  "destory",
];

// 策略模式
let starts = {};
//定义策略模式中的一些算法，（策略模式）保证当算法内部规则需要改变时候，使用该算法的地方不需要改变
starts.data = function (parentVal, childVal) {
  return parentVal || childVal;
}; // 合并全局书写的Vue.mixin 中的data和单个组件内的data
starts.computed = function (parentVal, childVal) {
  console.log(childVal, "childValchildVal");
  return childVal;
}; // 合并computed
starts.watch = function (parentVal, childVal) {
  return childVal;
}; // 合并watch
starts.methods = function (parentVal, childVal) {
  return parentVal || childVal;
}; // 合并methods

//合并components 全局定义的自定义组件  和 局部定义的自定义组件

starts.components = function (parentVal, childVal) {
  debugger
  //因为组件会 互相嵌套 父组件1-->子组件1--->孙组件1
  // 所以需要 子组件去 继承父组件内 所有的属性和方法 通过原型--这样子组件就可以访问父组件的功能
  const obj = Object.create(parentVal);
  // 父组件去添加子组件的 属性和方法
  for (let key in childVal) {
    obj[key] = childVal[key];
  }
  return obj; //最后的obj是 包含父组件和子组件的属性和方法

  // 所以渲染规则 是 如果局部--自定义组件存在那么就渲染，如果没有，那么就去原型上，===父组件，内去找自定义组件进行渲染。

};

// 遍历生命周期--添加生命周期算法--函数
HOOKS.forEach((hooks) => {
  starts[hooks] = mergeHook;
});

function mergeHook(parentVal, childVal) {
  // {created: [a,b,c],watch:[a,b]}

  if (childVal) {
    if (parentVal) {
      return parentVal.concat(childVal);
    } else {
      return [childVal]; //[a]
    }
  } else {
    return parentVal;
  }
}

export function mergeOptions(parent, child) {
  // child： 就是mixin中的对象
  console.log(parent, child, "parent-child"); //想要的结果 // Vue.options = {created: [a,b,c],watch:[a,b]}
  let options = {};
  //1. 组装
  // 如果有父亲 没用儿子
  for (let key in parent) {
    mergeField(key);
  }
  //2. 儿子有 父亲没用
  for (let key in child) {
    // {}
    mergeField(key); //调用方法
  }

  //声明 mergeField方法
  function mergeField(key) {
    // 根据key 策略模式
    if (starts[key]) {
      // created {create: [a]}
      //编辑 已经存在父亲 {created: [a]} 所有需要进行拼接 新的子到里面 /合并 生命周期或者 data watch等
      options[key] = starts[key](parent[key], child[key]); //调用上面定义的策略模式中定义的方法，parent[key]是数组  child[key]是function(){}
    } else {
      //新增 上面data,methods,watch不存在的属性到options对象中去
      options[key] = child[key] || parent[key];
    }
    //
  }
  return options;
}
